import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { SysDict } from '../../entities/sys-dict.entity';
import { SysDictData } from '../../entities/sys-dict-data.entity';
import { InjectRedis } from '@nestjs-modules/ioredis';
import Redis from 'ioredis';
import { CreateDictDataDto } from './dto/create-dict-data.dto';

@Injectable()
export class DictService {
  constructor(
    @InjectRepository(SysDict)
    private dictRepository: Repository<SysDict>,
    @InjectRepository(SysDictData)
    private dictDataRepository: Repository<SysDictData>,
    @InjectRedis() private readonly redis: Redis,
  ) {}

  /**
   * 获取字典列表
   */
  async getDictList(params: any) {
    const { dictCode, name, status, pageNum = 1, pageSize = 10 } = params;

    const queryBuilder = this.dictRepository
      .createQueryBuilder('dict')
      .where('dict.is_deleted = :isDeleted', { isDeleted: 0 });

    if (dictCode) {
      queryBuilder.andWhere('dict.dict_code LIKE :dictCode', {
        dictCode: `%${dictCode}%`,
      });
    }

    if (name) {
      queryBuilder.andWhere('dict.name LIKE :name', { name: `%${name}%` });
    }

    if (status !== undefined) {
      queryBuilder.andWhere('dict.status = :status', { status });
    }

    const total = await queryBuilder.getCount();
    const list = await queryBuilder
      .orderBy('dict.create_time', 'DESC')
      .skip((pageNum - 1) * pageSize)
      .take(pageSize)
      .getMany();

    return { total, list };
  }

  /**
   * 根据字典编码获取字典数据列表
   */
  async getDictDataByCode(
    dictCode: string,
    pageNum?: number,
    pageSize?: number,
    label?: string,
    value?: string,
  ) {
    // 如果没有提供分页参数且没有筛选条件，则尝试使用缓存
    if (pageNum === undefined && pageSize === undefined && !label && !value) {
      // 首先尝试从缓存获取
      const cacheKey = `dict:${dictCode}`;
      const cachedData = await this.redis.get(cacheKey);

      if (cachedData) {
        return JSON.parse(cachedData);
      }

      // 缓存不存在，从数据库查询
      const dictDataList = await this.dictDataRepository.find({
        where: { dictCode },
        order: { sort: 'ASC' },
      });

      // 将结果存入缓存，设置1小时过期
      if (dictDataList.length > 0) {
        await this.redis.set(
          cacheKey,
          JSON.stringify(dictDataList),
          'EX',
          3600,
        );
      }

      return dictDataList;
    }

    // 分页查询或者带筛选条件的查询
    const queryBuilder = this.dictDataRepository
      .createQueryBuilder('dictData')
      .where('dictData.dict_code = :dictCode', { dictCode })

    // 添加标签筛选条件
    if (label) {
      queryBuilder.andWhere('dictData.label LIKE :label', {
        label: `%${label}%`,
      });
    }

    // 添加值筛选条件
    if (value) {
      queryBuilder.andWhere('dictData.value LIKE :value', {
        value: `%${value}%`,
      });
    }

    // 按排序字段排序
    queryBuilder.orderBy('dictData.sort', 'ASC');

    // 获取总记录数
    const total = await queryBuilder.getCount();

    // 添加分页
    if (pageNum !== undefined && pageSize !== undefined) {
      queryBuilder.skip((pageNum - 1) * pageSize).take(pageSize);
    }

    // 执行查询
    const list = await queryBuilder.getMany();

    // 返回不同格式的结果，取决于是否有分页参数
    if (pageNum !== undefined && pageSize !== undefined) {
      return {
        total,
        list,
        pageNum,
        pageSize,
      };
    } else {
      return list;
    }
  }

  /**
   * 创建字典
   */
  async createDict(createDictDto: any) {
    const { dictCode } = createDictDto;

    // 检查是否存在相同的dictCode
    const existDict = await this.dictRepository.findOne({
      where: { dictCode, isDeleted: 0 },
    });
    if (existDict) {
      throw new Error('字典编码已存在');
    }

    const dict = this.dictRepository.create(createDictDto);
    return await this.dictRepository.save(dict);
  }

  /**
   * 更新字典
   */
  async updateDict(id: number, updateDictDto: any) {
    const dict = await this.dictRepository.findOne({ where: { id } });
    if (!dict) {
      throw new Error('字典不存在');
    }

    // 更新字典
    Object.assign(dict, updateDictDto);
    const result = await this.dictRepository.save(dict);

    // 如果修改了dictCode，需要清除相关缓存
    if (updateDictDto.dictCode && dict.dictCode !== updateDictDto.dictCode) {
      await this.redis.del(`dict:${dict.dictCode}`);
    }

    return result;
  }

  /**
   * 删除字典
   */
  async deleteDict(id: number) {
    const dict = await this.dictRepository.findOne({ where: { id } });
    if (!dict) {
      throw new Error('字典不存在');
    }

    // 逻辑删除
    dict.isDeleted = 1;
    await this.dictRepository.save(dict);

    // 清除缓存
    await this.redis.del(`dict:${dict.dictCode}`);

    return true;
  }

  /**
   * 创建字典数据项
   */
  async createDictData(createDictDataDto: CreateDictDataDto) {
    const dictData = this.dictDataRepository.create(createDictDataDto);
    const result = await this.dictDataRepository.save(dictData);

    // 清除相关缓存
    await this.redis.del(`dict:${dictData.dictCode}`);

    return result;
  }

  /**
   * 更新字典数据项
   */
  async updateDictData(id: number, updateDictDataDto: any) {
    const dictData = await this.dictDataRepository.findOne({ where: { id } });
    if (!dictData) {
      throw new Error('字典数据项不存在');
    }

    const oldDictCode = dictData.dictCode;

    // 更新字典数据项
    Object.assign(dictData, updateDictDataDto);
    const result = await this.dictDataRepository.save(dictData);

    // 清除相关缓存
    await this.redis.del(`dict:${oldDictCode}`);
    if (oldDictCode !== dictData.dictCode) {
      await this.redis.del(`dict:${dictData.dictCode}`);
    }

    return result;
  }

  /**
   * 删除字典数据项
   */
  async deleteDictData(id: number) {
    const dictData = await this.dictDataRepository.findOne({ where: { id } });
    if (!dictData) {
      throw new Error('字典数据项不存在');
    }

    // 删除字典数据项
    await this.dictDataRepository.remove(dictData);

    // 清除相关缓存
    await this.redis.del(`dict:${dictData.dictCode}`);

    return true;
  }

  /**
   * 刷新字典缓存
   */
  async refreshCache(dictCode?: string) {
    if (dictCode) {
      // 刷新特定字典的缓存
      const dictDataList = await this.dictDataRepository.find({
        where: { dictCode, status: 1 },
        order: { sort: 'ASC' },
      });

      await this.redis.set(
        `dict:${dictCode}`,
        JSON.stringify(dictDataList),
        'EX',
        3600,
      );
      return true;
    }

    // 刷新所有字典的缓存
    const dicts = await this.dictRepository.find({
      where: { isDeleted: 0, status: 1 },
    });

    for (const dict of dicts) {
      const dictDataList = await this.dictDataRepository.find({
        where: { dictCode: dict.dictCode, status: 1 },
        order: { sort: 'ASC' },
      });

      await this.redis.set(
        `dict:${dict.dictCode}`,
        JSON.stringify(dictDataList),
        'EX',
        3600,
      );
    }

    return true;
  }

  async getAllDictWithData(dictCodes?: string[]) {
    // 查询所有活跃的字典
    let dicts: SysDict[];

    if (dictCodes && dictCodes.length > 0) {
      // 如果指定了字典编码，则只查询这些字典
      dicts = await this.dictRepository.find({
        where: {
          dictCode: In(dictCodes),
          isDeleted: 0,
          status: 1,
        },
      });
    } else {
      // 否则查询所有活跃字典
      dicts = await this.dictRepository.find({
        where: {
          isDeleted: 0,
          status: 1,
        },
      });
    }

    // 构建结果数组
    const result = [];

    // 对于每个字典，获取其数据列表
    for (const dict of dicts) {
      // 尝试从缓存获取字典数据
      const cacheKey = `dict:${dict.dictCode}`;
      let dictDataList = null;

      const cachedData = await this.redis.get(cacheKey);
      if (cachedData) {
        dictDataList = JSON.parse(cachedData);
      } else {
        // 缓存不存在，从数据库查询
        dictDataList = await this.dictDataRepository.find({
          where: { dictCode: dict.dictCode, status: 1 },
          order: { sort: 'ASC' },
        });

        // 将结果存入缓存，设置1小时过期
        if (dictDataList.length > 0) {
          await this.redis.set(
            cacheKey,
            JSON.stringify(dictDataList),
            'EX',
            3600,
          );
        }
      }

      // 格式化字典数据，只保留必要的字段
      const formattedDictData = dictDataList.map((item) => ({
        value: item.value,
        label: item.label,
        tagType: item.tagType,
      }));

      // 构建字典项
      result.push({
        name: dict.name,
        dictCode: dict.dictCode,
        dictDataList: formattedDictData,
      });
    }

    return result;
  }

  /**
   * 根据ID获取字典数据项
   */
  async getDictDataById(id: number) {
    const dictData = await this.dictDataRepository.findOne({ where: { id } });
    if (!dictData) {
      throw new Error('字典数据项不存在');
    }
    return dictData;
  }
}
